# coding=utf-8
from __future__ import print_function, absolute_import
from gm.api import *
import winsound

import datetime
import numpy as np
import pandas as pd

def init(context):
    context.frequency = '60s'
    context.short = 5
    context.long = 20
    context.symbol = ['CZCE.CF409']
    context.volume = 1
    context.period = context.long + 1
    subscribe(context.symbol, context.frequency, count=context.period, unsubscribe_previous=True)

def on_bar(context, bars):
    account = context.account()
    cash = account.cash
    print(f"可用资金: {cash['available']:.2f},\
            账户的浮动盈亏: {cash['pnl']:.2f},\
            账户的累计盈亏:{cash['cum_pnl']:.2f}")
    symbol = context.symbol[0]
    print(symbol, context.now)
    prices = context.data(symbol, context.frequency, context.period, fields='close')
    short_avg = prices['close'].rolling(context.short).mean().values
    long_avg = prices['close'].rolling(context.long).mean().values

    positions = get_position()
    position_long = [p for p in positions if p['symbol'] == symbol and p['side'] == PositionSide_Long]
    position_short = [p for p in positions if p['symbol'] == symbol and p['side'] == PositionSide_Short]

    # 当死叉并且没有空头仓位（有空头仓位不操作）
    if long_avg[-2] <= short_avg[-2] and long_avg[-1] > short_avg[-1] and not position_short:
	# 当没有多头仓位，开空仓
        if not position_long:
            order_volume(symbol=symbol, volume=context.volume, side=OrderSide_Sell, position_effect=PositionEffect_Open, order_type=OrderType_Market)
            # 播放报警声
            winsound.Beep(1000, 2000)  # 参数：频率（Hz），持续时间（毫秒）
	# 否则（有多头仓位），多头平仓
        else:
            order_volume(symbol=symbol, volume=context.volume, side=OrderSide_Sell, position_effect=PositionEffect_Close, order_type=OrderType_Market)
            order_volume(symbol=symbol, volume=context.volume, side=OrderSide_Sell, position_effect=PositionEffect_Open, order_type=OrderType_Market)
            # 播放报警声
            winsound.Beep(1000, 2000)  # 参数：频率（Hz），持续时间（毫秒）
    # 当金叉并且没有多头仓位
    if short_avg[-2] <= long_avg[-2] and short_avg[-1] > long_avg[-1] and not position_long:
	# 如果没有空头仓位，开多仓
        if not position_short:
            order_volume(symbol=symbol, volume=context.volume, side=OrderSide_Buy, position_effect=PositionEffect_Open, order_type=OrderType_Market)
            # 播放报警声
            winsound.Beep(1000, 2000)  # 参数：频率（Hz），持续时间（毫秒）
    # 否则（有空头仓位），空头平仓。
        else:
            order_volume(symbol=symbol, volume=context.volume, side=OrderSide_Buy, position_effect=PositionEffect_Close, order_type=OrderType_Market)
            order_volume(symbol=symbol, volume=context.volume, side=OrderSide_Buy, position_effect=PositionEffect_Open, order_type=OrderType_Market)
            # 播放报警声
            winsound.Beep(1000, 2000)  # 参数：频率（Hz），持续时间（毫秒）
            
def on_order_status(context, order):
    symbol = order['symbol']
    price = order['price']
    volume = order['volume']
    status = order['status']
    side = order['side']
    effect = order['position_effect']
    order_type = order['order_type']
    if status == 3:
        if effect == 1:
            side_effect = '开多仓' if side == 1 else '开空仓'
        else:
            side_effect = '平空仓' if side == 1 else '平多仓'
        order_type_word = '限价' if order_type == 1 else '市价'
        print('{}:标的：{}，操作：以{}{}，委托价格：{}，委托数量：{}'.format(context.now, symbol, order_type_word, side_effect, price, volume))

def on_backtest_finished(context, indicator):
    print('*' * 50)
    print('回测已完成，请通过右上角“回测历史”功能查询详情。')



if __name__ == '__main__':
    '''
        strategy_id策略ID, 由系统生成
        filename文件名, 请与本文件名保持一致
        mode运行模式, 实时模式:MODE_LIVE回测模式:MODE_BACKTEST
        token绑定计算机的ID, 可在系统设置-密钥管理中生成
        backtest_start_time回测开始时间
        backtest_end_time回测结束时间
        backtest_adjust股票复权方式, 不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POST
        backtest_initial_cash回测初始资金
        backtest_commission_ratio回测佣金比例
        backtest_slippage_ratio回测滑点比例
        backtest_match_mode市价撮合模式，以下一tick/bar开盘价撮合:0，以当前tick/bar收盘价撮合：1
        '''
    run(strategy_id='248dd6af-3e6c-11ef-9dfd-0050b6c7fa6e',
        filename='main.py',
        mode=MODE_BACKTEST,
        token='ca9c4532786a122aa5ceb3fd726432862e046f91',
        backtest_start_time='2024-07-01 08:00:00',
        backtest_end_time='2024-07-10 16:00:00',
        backtest_adjust=ADJUST_PREV,
        backtest_initial_cash=10000000,
        backtest_commission_ratio=0.0001,
        backtest_slippage_ratio=0.0001,
        backtest_match_mode=1)

